import cmd
import sys
import os
import functools
import json
import asyncio
from typing import List, Dict, Any, Optional, Callable
import shlex


# ==============================================================================
#  设置环境路径，加载 pocketflow
# ==============================================================================
# .
# ├── base_code/
# │   ├── __init__.py  <- pocketflow 代码在这里
# │   └── common.py    <- ToolSystem and UI
# ├── tools/           <- TODO ...
# │   ├── pdf_tools    <- PDF read/write/search Tools
# │   └── sys_tools    <- System tools
# └── 4.prompt_support
# │   ├── react_terminal.py
# │   ├── react_agent.py
# │   ├── mcp_server   <- Local MCP server
# │   └── mcp_client   <- test MCP tools
# │   └── tools        <- test MCP tools
# │       └── example_tool       <- tool template registered on MCP server

from react_agent import *     # also init global tools

# =======================================================================
#  1. SimpleReActShell (应用层)
# =======================================================================
class SimpleReActShell(cmd.Cmd):
    """
    交互式 Shell，负责与用户交互并将指令传递给 ReActAgent。
    """
    ui = UIAgent(GLOBAL_TOOL_SYSTEM)
    intro = ui.show_intro()
    prompt = "user> "
    cmd_list = {"show", "exit", "quit", "cd", "pwd", "list_tools", "debug", "^D"}

    def __init__(self):
        super().__init__()
        self.cmd_agent = ReActAgent(GLOBAL_TOOL_SYSTEM)

    # -----------------------
    # 1️在这里统一解析输入
    # -----------------------
    def parse_line(self, line):
        """解析输入行，判断是工具命令还是自然语言"""
        line = line.strip()
        if not line:
            return None, None, line

        parts = line.split()
        cmd_name = parts[0]
        args = " ".join(parts[1:])

        # 如果是内部工具命令
        if cmd_name in self.cmd_list:
            print("执行内部命令")
            return cmd_name, args, line
        elif GLOBAL_TOOL_SYSTEM.has_tool(cmd_name):  # 是注册工具
            print("执行注册工具")
            return "tool", cmd_name, args
        else:
            # 让 onecmd 走到 default()
            return None, line, line

    # -----------------------
    # 2️⃣ 核心执行逻辑
    # -----------------------
    def onecmd(self, line):
        """根据 parse_line 的结果决定执行命令还是自然语言"""
        cmd_name, arg1, arg2 = self.parse_line(line)

        if cmd_name is None:
            return self.default(line)

        elif cmd_name == "tool":
            print(f"{tool}  {arg1} {arg2}")

            return self.do_tool(arg1, arg2)
        else:
            return super().onecmd(line)

    # -----------------------
    # 执行工具命令
    # -----------------------
    def do_tool(self, cmd_name, arg):
        """执行注册的工具"""
        tool_name = cmd_name
        args_list = shlex.split(arg)
        print(f"Run tool {tool_name} with {args_list}")
        result = asyncio.run(GLOBAL_TOOL_SYSTEM.run_tool(tool_name, *args_list))
        if result:
            print(result)

        return False

    def default(self, line: str):
        print("执行自然语言指令")
        try:
            if not line.strip():
                # 用户只是按了回车
                return  # 什么也不做
            # 运行 Agent 的主流程
            result = asyncio.run(self.cmd_agent.process_command_async(line))
            # print(f"\n🤖 FakeAgent is working----\n")
        except Exception as e:
            print(f"\n💥 系统顶层异常: {e}")

    def do_cd(self, arg):
        path = arg.strip() or "."
        try:
            os.chdir(path)
            print(f"已切换到目录：{os.getcwd()}")
        except Exception as e:
            print(f"错误：{e}")

    def do_pwd(self, arg):
        path = os.getcwd()
        print(path)

    def do_show(self, arg):
        self.cmd_agent.show_memo()

    # def do_ls(self, arg):
    #     asyncio.run(GLOBAL_TOOL_SYSTEM.run_tool("ls", {"arg": "."}))

    def do_list_tools(self, arg):
        tools_list = GLOBAL_TOOL_SYSTEM.list_tools()
        print(f"{'名称':<12} {'描述'}")
        print("-" * 60)
        for tool in tools_list:
            name = tool.get('name', 'N/A')
            desc = tool.get('description', '无描述').strip()
            print(f"{name:<12} {desc}")
    def do_debug(self, arg):
        print("Debug >>")

    def do_exit(self, arg):
        """退出程序。"""
        print("\n👋 感谢使用，再见！")
        return True

    def do_EOF(self, arg):
        """处理 Ctrl+D 退出。"""
        print()
        return self.do_exit(arg)

    def do_quit(self, arg):
        """退出系统"""
        print("退出系统。")
        return True


async def app_init():
    # 配置 MCP 服务器地址，如果不需要则设为 None
    MCP_SERVER_URL = "http://127.0.0.1:9000"
    await GLOBAL_TOOL_SYSTEM.load_tools_from_mcp("http://127.0.0.1:9000")

# =======================================================================
#  主流程
# =======================================================================
def main():
    """程序主入口。"""
    # 启动交互式 Shell
    shell = SimpleReActShell()
    try:
        shell.cmdloop()
    except KeyboardInterrupt:
        print("\n👋 检测到中断，程序退出。")
        sys.exit(0)

if __name__ == '__main__':
    asyncio.run(app_init())
    main()
